using Microsoft.EntityFrameworkCore;
using RAG.Application.Interfaces;
using RAG.Application.Commands;
using RAG.Infrastructure.Data;
using RAG.Domain.Entities.App;

namespace RAG.Application.Services;

/// <summary>
/// 向量管理服务实现
/// </summary>
public class AppVectorService : IAppVectorService
{
    private readonly RagDbContext _db;
    private readonly IVectorService _vectorService;

    public AppVectorService(RagDbContext db, IVectorService vectorService)
    {
        _db = db;
        _vectorService = vectorService;
    }

    /// <summary>
    /// 获取向量列表
    /// </summary>
    public async Task<ApiResult> GetVectorListAsync(VectorListQueryDto query)
    {
        try
        {
            var queryBuilder = _db.Vectors
                .Include(v => v.DocumentChunk)
                .ThenInclude(dc => dc.Document)
                .Where(v => !v.IsDeleted)
                .AsQueryable();

            // 关键词搜索
            if (!string.IsNullOrEmpty(query.Keyword))
            {
                queryBuilder = queryBuilder.Where(v => 
                    v.DocumentChunk.DocumentChunkContent.Contains(query.Keyword));
            }

            // 维度过滤
            if (query.Dimension.HasValue)
            {
                queryBuilder = queryBuilder.Where(v => v.Embedding.Length == query.Dimension.Value);
            }

            var totalCount = await queryBuilder.CountAsync();

            var vectorList = await queryBuilder
                .OrderByDescending(v => v.CreatedAt)
                .Skip((query.Page - 1) * query.PageSize)
                .Take(query.PageSize)
                .Select(v => new
                {
                    Id = v.VectorId,
                    Text = v.DocumentChunk.DocumentChunkContent,
                    Dimension = v.Embedding.Length,
                    VectorLength = CalculateVectorLength(v.Embedding),
                    CreatedAt = v.CreatedAt,
                    DocumentTitle = v.DocumentChunk.Document.DocumentTitle
                })
                .ToListAsync();

            var result = new
            {
                VectorList = vectorList,
                TotalCount = totalCount,
                Page = query.Page,
                PageSize = query.PageSize,
                TotalPages = (int)Math.Ceiling((double)totalCount / query.PageSize)
            };

            return ApiResult.Success("获取向量列表成功", result);
        }
        catch (Exception ex)
        {
            return ApiResult.Failed((int)ApiStatusCode.INTERNAL_ERROR, $"获取向量列表失败: {ex.Message}");
        }
    }

    /// <summary>
    /// 获取向量详情
    /// </summary>
    public async Task<ApiResult> GetVectorDetailAsync(Guid vectorId)
    {
        try
        {
            var vector = await _db.Vectors
                .Include(v => v.DocumentChunk)
                .ThenInclude(dc => dc.Document)
                .FirstOrDefaultAsync(v => v.VectorId == vectorId && !v.IsDeleted);

            if (vector == null)
            {
                return ApiResult.Failed((int)ApiStatusCode.NOT_FOUND, "向量不存在");
            }

            var result = new
            {
                Id = vector.VectorId,
                Text = vector.DocumentChunk.DocumentChunkContent,
                Dimension = vector.Embedding.Length,
                VectorLength = CalculateVectorLength(vector.Embedding),
                Embedding = vector.Embedding,
                CreatedAt = vector.CreatedAt,
                DocumentTitle = vector.DocumentChunk.Document.DocumentTitle,
                DocumentId = vector.DocumentChunk.DocumentId
            };

            return ApiResult.Success("获取向量详情成功", result);
        }
        catch (Exception ex)
        {
            return ApiResult.Failed((int)ApiStatusCode.INTERNAL_ERROR, $"获取向量详情失败: {ex.Message}");
        }
    }

    /// <summary>
    /// 生成单个向量
    /// </summary>
    public async Task<ApiResult> GenerateVectorAsync(GenerateVectorDto dto)
    {
        try
        {
            // 生成向量
            var embedding = await _vectorService.GenerateEmbeddingAsync(dto.Text);

            // 创建临时文档块来存储向量
            var documentChunk = new DocumentChunk
            {
                Id = Guid.NewGuid(),
                DocumentId = Guid.Empty, // 临时ID
                ChunkIndex = 0,
                DocumentChunkContent = dto.Text,
                TokenCount = dto.Text.Length,
                CreatedAt = DateTime.UtcNow,
                UpdatedAt = DateTime.UtcNow
            };

            _db.DocumentChunks.Add(documentChunk);

            // 创建向量记录
            var vector = new Vector
            {
                VectorId = Guid.NewGuid(),
                DocumentChunkId = documentChunk.Id,
                Embedding = embedding,
                CreatedAt = DateTime.UtcNow,
                UpdatedAt = DateTime.UtcNow
            };

            _db.Vectors.Add(vector);
            await _db.SaveChangesAsync();

            var result = new
            {
                Id = vector.VectorId,
                Text = dto.Text,
                Dimension = embedding.Length,
                VectorLength = CalculateVectorLength(embedding),
                CreatedAt = vector.CreatedAt
            };

            return ApiResult.Success("向量生成成功", result);
        }
        catch (Exception ex)
        {
            return ApiResult.Failed((int)ApiStatusCode.INTERNAL_ERROR, $"生成向量失败: {ex.Message}");
        }
    }

    /// <summary>
    /// 批量生成向量
    /// </summary>
    public async Task<ApiResult> BatchGenerateVectorsAsync(BatchGenerateVectorDto dto)
    {
        try
        {
            var results = new List<object>();

            foreach (var text in dto.Texts)
            {
                // 生成向量
                var embedding = await _vectorService.GenerateEmbeddingAsync(text);

                // 创建临时文档块
                var documentChunk = new DocumentChunk
                {
                    Id = Guid.NewGuid(),
                    DocumentId = Guid.Empty,
                    ChunkIndex = 0,
                    DocumentChunkContent = text,
                    TokenCount = text.Length,
                    CreatedAt = DateTime.UtcNow,
                    UpdatedAt = DateTime.UtcNow
                };

                _db.DocumentChunks.Add(documentChunk);

                // 创建向量记录
                var vector = new Vector
                {
                    VectorId = Guid.NewGuid(),
                    DocumentChunkId = documentChunk.Id,
                    Embedding = embedding,
                    CreatedAt = DateTime.UtcNow,
                    UpdatedAt = DateTime.UtcNow
                };

                _db.Vectors.Add(vector);

                results.Add(new
                {
                    Id = vector.VectorId,
                    Text = text,
                    Dimension = embedding.Length,
                    VectorLength = CalculateVectorLength(embedding),
                    CreatedAt = vector.CreatedAt
                });
            }

            await _db.SaveChangesAsync();

            var result = new
            {
                GeneratedVectors = results,
                Count = results.Count
            };

            return ApiResult.Success($"批量生成 {results.Count} 个向量成功", result);
        }
        catch (Exception ex)
        {
            return ApiResult.Failed((int)ApiStatusCode.INTERNAL_ERROR, $"批量生成向量失败: {ex.Message}");
        }
    }

    /// <summary>
    /// 删除向量
    /// </summary>
    public async Task<ApiResult> DeleteVectorAsync(Guid vectorId)
    {
        try
        {
            var vector = await _db.Vectors
                .Include(v => v.DocumentChunk)
                .FirstOrDefaultAsync(v => v.VectorId == vectorId && !v.IsDeleted);

            if (vector == null)
            {
                return ApiResult.Failed((int)ApiStatusCode.NOT_FOUND, "向量不存在");
            }

            // 软删除向量
            vector.IsDeleted = true;
            vector.UpdatedAt = DateTime.UtcNow;

            // 软删除关联的文档块
            vector.DocumentChunk.IsDeleted = true;
            vector.DocumentChunk.UpdatedAt = DateTime.UtcNow;

            await _db.SaveChangesAsync();

            return ApiResult.Success("向量删除成功");
        }
        catch (Exception ex)
        {
            return ApiResult.Failed((int)ApiStatusCode.INTERNAL_ERROR, $"删除向量失败: {ex.Message}");
        }
    }

    /// <summary>
    /// 向量相似度搜索
    /// </summary>
    public async Task<ApiResult> SearchVectorSimilarityAsync(VectorSimilaritySearchDto dto)
    {
        try
        {
            // 生成查询向量
            var queryVector = await _vectorService.GenerateEmbeddingAsync(dto.Text);

            // 获取所有向量数据
            var vectors = await _db.Vectors
                .Include(v => v.DocumentChunk)
                .Where(v => !v.IsDeleted)
                .ToListAsync();

            var vectorData = vectors.Select(v => new VectorData
            {
                ChunkId = v.DocumentChunkId,
                Vector = v.Embedding,
                Content = v.DocumentChunk.DocumentChunkContent
            }).ToList();

            // 执行相似度搜索
            var searchResults = await _vectorService.SearchSimilarVectorsAsync(queryVector, vectorData, dto.Limit);

            // 过滤相似度阈值
            var filteredResults = searchResults
                .Where(r => r.Similarity >= dto.Threshold)
                .Select(r => new
                {
                    Text = r.Content,
                    Similarity = r.Similarity
                })
                .ToList();

            var result = new
            {
                QueryText = dto.Text,
                Threshold = dto.Threshold,
                Data = filteredResults,
                TotalResults = filteredResults.Count
            };

            return ApiResult.Success("向量相似度搜索成功", result);
        }
        catch (Exception ex)
        {
            return ApiResult.Failed((int)ApiStatusCode.INTERNAL_ERROR, $"向量相似度搜索失败: {ex.Message}");
        }
    }

    /// <summary>
    /// 向量相似度搜索（仅返回列表，便于前端直接渲染）
    /// </summary>
    public async Task<ApiResult> SearchVectorSimilarityListAsync(VectorSimilaritySearchDto dto)
    {
        try
        {
            var queryVector = await _vectorService.GenerateEmbeddingAsync(dto.Text);

            var vectors = await _db.Vectors
                .Include(v => v.DocumentChunk)
                .Where(v => !v.IsDeleted)
                .ToListAsync();

            var vectorData = vectors.Select(v => new VectorData
            {
                ChunkId = v.DocumentChunkId,
                Vector = v.Embedding,
                Content = v.DocumentChunk.DocumentChunkContent
            }).ToList();

            var searchResults = await _vectorService.SearchSimilarVectorsAsync(queryVector, vectorData, dto.Limit);

            var filteredResults = searchResults
                .Where(r => r.Similarity >= dto.Threshold)
                .Select(r => new { Text = r.Content, Similarity = r.Similarity })
                .ToList();

            return ApiResult.Success("向量相似度搜索成功", filteredResults);
        }
        catch (Exception ex)
        {
            return ApiResult.Failed((int)ApiStatusCode.INTERNAL_ERROR, $"向量相似度搜索失败: {ex.Message}");
        }
    }

    /// <summary>
    /// 获取向量统计信息
    /// </summary>
    public async Task<ApiResult> GetVectorStatisticsAsync()
    {
        try
        {
            var totalVectors = await _db.Vectors.Where(v => !v.IsDeleted).CountAsync();
            var totalDocuments = await _db.Documents.Where(d => !d.IsDeleted).CountAsync();
            var totalChunks = await _db.DocumentChunks.Where(dc => !dc.IsDeleted).CountAsync();

            // 获取维度分布
            var dimensionStats = await _db.Vectors
                .Where(v => !v.IsDeleted)
                .GroupBy(v => v.Embedding.Length)
                .Select(g => new { Dimension = g.Key, Count = g.Count() })
                .ToListAsync();

            var result = new
            {
                TotalVectors = totalVectors,
                TotalDocuments = totalDocuments,
                TotalChunks = totalChunks,
                DimensionDistribution = dimensionStats
            };

            return ApiResult.Success("获取向量统计信息成功", result);
        }
        catch (Exception ex)
        {
            return ApiResult.Failed((int)ApiStatusCode.INTERNAL_ERROR, $"获取向量统计信息失败: {ex.Message}");
        }
    }

    /// <summary>
    /// 计算向量长度
    /// </summary>
    private static double CalculateVectorLength(float[] vector)
    {
        return Math.Sqrt(vector.Sum(x => x * x));
    }
}
